package com.woniu.aop;
import com.woniu.annotation.BaseAnnotation;
import com.woniu.annotation.ObjectAnnotation;
import com.woniu.exception.DIYException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Set;

/**
 * 日志切面类
 */
@Aspect
@Component
@Slf4j
public class WebLogAspect {

    @Autowired
    private Validator validator;
    /**
     * 处理器
     * @return
     */
    @Around("execution(* com.woniu.apiImpl.*.*(..))")

    public Object around(ProceedingJoinPoint pjt) throws Throwable {
        Object[] args = pjt.getArgs();
        String name = pjt.getSignature().getName();
        log.info("进入接口：{},参数：{}", name, args);
        //获取所有注解
        Annotation[][] parameterAnnotations
                = ((MethodSignature) pjt.getSignature()).getMethod().getParameterAnnotations();
        //遍历数组获取参数下标
        for (Annotation[] parameterAnnotation : parameterAnnotations) {
            //获取参数下标
            int index = ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);
            for (Annotation annotation : parameterAnnotation) {//遍历参数注解
                ArrayList<String> messages = new ArrayList<>();
                //判断参数是否有这个注解
                if (annotation instanceof ObjectAnnotation || annotation instanceof BaseAnnotation) {
                    //获取验证消息
                    Set<ConstraintViolation<Object>> validate
                            = validator.validate(args[index]);
                    //判断是否有验证消息
                    if (validate.size() > 0) {
                        //遍历验证消息
                        for (ConstraintViolation<Object> violation : validate) {
                            //添加到消息集合
                            messages.add(violation.getMessage());
                        }
                    }
                }
//                有验证消息抛出异常
                if(messages.size()>0) {
                    log.error("验证失败：{}",messages.toString());
                    throw new DIYException(10000, messages.toString());
                }
            }
        }
        Object result = pjt.proceed(args);
        log.info("离开接口: {},返回值：{}", name, result);
        return result;
    }

}
